class FragmentsController < ApplicationController
  # GET /fragments
  # GET /fragments.xml
  def index
    @fragments = Fragment.find(:all)

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @fragments }
    end
  end

  # GET /fragments/1
  # GET /fragments/1.xml
  def show
    @fragment = Fragment.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @fragment }
    end
  end

  # GET /fragments/new
  # GET /fragments/new.xml
  def new
    @fragment = Fragment.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @fragment }
    end
  end

  # GET /fragments/1/edit
  def edit
    @fragment = Fragment.find(params[:id])
  end

  # POST /fragments
  # POST /fragments.xml
  def create
    @fragment = Fragment.new(params[:fragment])

    if @fragment.save
      content = params[:fragment]['file'].read
      begin
        Fragment.create_from_csv_string @fragment, content
      rescue
        logger.info "\nError while importing fragment!\n#{$!}\n\n#{$!.backtrace.join('\r\n')}"
        @fragment = nil
      end
    else
      logger.info "\nSomething went wrong while trying to save the fragment"
      @fragment = nil      
    end 

    respond_to do |format|
      if @fragment
        flash[:notice] = 'Fragment was successfully created.'
        format.html { redirect_to(@fragment) }
        format.xml  { render :xml => @fragment, :status => :created, :location => @fragment }
      else
        flash[:error] = "There was an error while importing your fragment"
        format.html { render :action => "new" }
        format.xml  { render :xml => @fragment.errors, :status => :unprocessable_entity }
      end
    end
  end
  

  # PUT /fragments/1
  # PUT /fragments/1.xml
  def update
    @fragment = Fragment.find(params[:id])

    respond_to do |format|
      if @fragment.update_attributes(params[:fragment])
        flash[:notice] = 'Fragment was successfully updated.'
        format.html { redirect_to(@fragment) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @fragment.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /fragments/1
  # DELETE /fragments/1.xml
  def destroy
    @fragment = Fragment.find(params[:id])
    @fragment.destroy

    respond_to do |format|
      format.html { redirect_to(fragments_url) }
      format.xml  { head :ok }
    end
  end

  def mappings
    @fragment = Fragment.find(params[:id])

    respond_to do |format|
      format.html
      format.xml { send_data( render_to_string( :file => "fragments/mappings.xml.builder", :type => "builder" ), :filename => "#{@fragment.name}_mappings.xml", :type => "text/xml" ) }
    end
  end

  def import_mappings
    @fragment = Fragment.find params[:id]
    @core_fragments = Fragment.cores
  end

  def upload_mappings
    logger.info "Params: #{params.inspect}"
    @fragment = Fragment.find params[:id]
    @map_to_fragment_id = params[:map_to_fragment_id]    
    content = params[:file].read
    begin
      @fragment.import_mappings_from_csv @map_to_fragment_id, content, @user
    rescue
      # TODO print the exception
      logger.error "\n\n**************************There was an error while importing the mappings!**************************\n"
      logger.error "Error: #{$!}"
      logger.error "Stacktrace:\n#{$!.backtrace.join("\r\n")}"
      flash[:error] = "ERROR!  Something went wrong while importing your mappings.  Some or all of your mappings may not have been imported.  Please contact your SHRIMP administrator."
    end

    redirect_to fragments_path
  end

  def search
    @results = Array.new

    unless params[:site_fragment_id].blank?
      @selected_concept = Concept.find(params[:search_selected_concept_id])
      @site_fragment = Fragment.find(params[:site_fragment_id])
      @core_institution = Institution.find(:first, :conditions => ["lower(name) like ?", "core"])
      @core_fragment = Fragment.find(:first, :conditions => ["fragment_type_id = ? AND institution_id = ?", @site_fragment.fragment_type_id, @core_institution.id])
      @search_text = params[:search_text].strip
      escaped_search_text = StringUtil.escape_sql(@search_text).downcase
      @include_attrs = params[:include_attrs]
      @dir = params[:dir] || "ASC"

      @sort_by = params[:sort_by]
      case @sort_by
      when "name", "local_key"
        sqlsort = true      
      end

      if !@search_text.blank? && @core_fragment
        sql = "SELECT * FROM #{Concept.table_name} WHERE fragment_id = #{@core_fragment.id} AND lower(name) like '%#{escaped_search_text}%' "
        sql << " UNION "
        sql << "SELECT * FROM #{Concept.table_name} WHERE fragment_id = #{@core_fragment.id} AND lower(local_key) LIKE '%#{escaped_search_text}%' "

        if @include_attrs
          sql << " UNION "
          sql << "SELECT #{Concept.table_name}.* FROM #{Concept.table_name} JOIN #{Attribute.table_name} ON #{Concept.table_name}.id = #{Attribute.table_name}.concept_id WHERE #{Concept.table_name}.fragment_id = #{@core_fragment.id} AND lower(#{Attribute.table_name}.`value`) like '%#{escaped_search_text}%'"
        end

        sql << " ORDER BY #{@sort_by} #{@dir}" if sqlsort
        
        @results = Concept.find_by_sql sql
      end
    end           

    order_concepts

    render :partial => "search_results"
  end
  

  private
  def order_concepts
    @results.sort! do |a, b|
      a_attr = a.attrs.select {|attr| attr.name == @sort_by }.first
      b_attr = b.attrs.select {|attr| attr.name == @sort_by }.first

      a_val = a_attr.value unless a_attr.blank?
      b_val = b_attr.value unless b_attr.blank?

      retval = 0
      if !a_val.blank? && !b_val.blank?
        retval = a_val <=> b_val
      elsif a_val.blank? && b_val.blank?
        retval = 0
      elsif a_val.blank?
        retval = 1
      else 
        retval = -1
      end

      @dir == "ASC" ? retval : retval*(-1)
    end

  end

end
